#============================================================
#	Card Item List
#============================================================
# @datetime: 2022-5-4 20:18:30
#============================================================
class_name CardItemList
extends Control


export var _card : PackedScene


var _from : int = 0
var _to : int = 0
var _duration : float = 0.0
var _interval : float = 0.0
var _trans_type : int = 0
var _ease_type : int = 2

# 间隔的卡片属性 from 的增量
var _from_step = null
# 间隔的卡片属性 to 时的增量
var _to_step = null

# 计时器任务
var _timer_task = TimerTask.new()

# 卡片数量
var _card_count : int = 0
# 正在 reset
var _reseting = false



#============================================================
#   Set/Get
#============================================================
func get_cards(init_card: bool = false) -> Array:
	var cards = []
	for child in get_children():
		if child is CardItem:
			if init_card:
				_init_card_prop(child)
			cards.append(child)
	_card_count = cards.size()
	return cards

func get_card_count() -> int:
	return _card_count


#============================================================
#   内置
#============================================================
func _ready():
	get_tree().current_scene.call_deferred("add_child", _timer_task)
	_to = get_cards().size()

#============================================================
#   自定义
#============================================================
##  添加卡片
## @texture  卡片图片
func add_card(texture: Texture):
	var card = _card.instance()
	add_child(card)


##  显示所有卡片
func show_all_card():
	for card in get_cards():
		card.get_icon_node().modulate.a = 1.0

##  隐藏所有卡片
func hide_all_card():
	# 调用完这个方法最好 yield(get_tree(), "idle_frame") 等待一帧间隔
	# 否则可能会有其他意外效果
	for card in get_cards():
		card.get_icon_node().modulate.a = 0.0

##  从这个卡片位置开始
## @value  
## @return  
func from(value: int) -> CardItemList:
	_from = value
	return self

##  到这个卡片位置结束
## @value  
## @return  
func to(value: int) -> CardItemList:
	_to = value
	return self

##  动画持续时间
## @value  
## @return  
func duration(value: float) -> CardItemList:
	_duration = value
	return self

##  卡片间隔播放的时间
## @value  
## @return  
func interval(value: float) -> CardItemList:
	_interval = value
	return self

func trans_type(value) -> CardItemList:
	_trans_type = value
	return self

func ease_type(value) -> CardItemList:
	_ease_type = value
	return self

func from_step(value) -> CardItemList:
	_from_step = value
	return self

func to_step(value) -> CardItemList:
	_to_step = value
	return self


##  重置属性
func _reset() -> void:
	if not _reseting:
		# 一帧内生效一次
		_reseting = true
		yield(get_tree(), "idle_frame")
		_reseting = false
		force_reset()

##  强制 reset
func force_reset() -> CardItemList:
	_from = 0
	_to = get_card_count()
	_duration = 0.0
	_interval = 0.0
	_from_step = null
	_to_step = null
	return self

##  完成
## @return  
func finish() -> void:
	force_reset()

##  检查设置是否正常
func _inspect() -> void:
	assert(_duration > 0, "duration （持续时间）必须超过 0！请 \"duration(持续时间)\" 进行设置！")
	


##  初始化卡片的属性
func _init_card_prop(card: CardItem) -> CardItem:
	card.set_duration(_duration)
	card.set_trans_type(_trans_type)
	card.set_ease_type(_ease_type)
	return card


##  从 from 到 to 索引的卡片
## @return  
func _from_to_card() -> Array:
	var list = get_cards()
	var cards = []
	for i in range(_from, _to):
		cards.append(list[i])
	return cards


##  初始偏移 
## @offset  
## @return  
func init_offset(offset: Vector2) -> CardItemList:
	# 初始化偏移
	var v = Vector2(0,0)
	if offset != Vector2(0,0):
		var cards : Array = _from_to_card()
		for idx in cards.size():
			var card = _init_card_prop(cards[idx])
			if _to_step:
				v = _to_step * idx
			_timer_task.add_task(
				idx * _interval
				, card, "add_card_position", [offset + v]
			)
	return self


##  初始化位置 
## @position  
## @return  
func init_position(position: Vector2, global: bool = false) -> CardItemList:
	var v = Vector2(0,0)
	var cards : Array = _from_to_card()
	for idx in cards.size():
		var card = _init_card_prop(cards[idx])
		if _to_step:
			v = _to_step * idx
		_timer_task.add_task(
			idx * _interval
			, card, "set_card_position", [position + v]
		)
	return self


#============================================================
#   播放动画
#============================================================

##  渐隐/渐出
## @from  开始的 alpha 值
## @to  结束的 alpha 值
## @return  
func fade(
	from: float, 
	to: float
) -> CardItemList:
	_inspect()
	var list : Array = _from_to_card()
	for idx in list.size():
		var card : CardItem = _init_card_prop(list[idx])
		if _from_step: from += _from_step * idx
		if _to_step: to += _to_step * idx
		_timer_task.add_task(
			idx * _interval, 
			card, "fade", [from, to]
		)
	_reset()
	return self


##  弹出
## @velocity  移动向量
## @return    
func eject(velocity: Vector2) -> CardItemList:
	_inspect()
	var cards : Array = _from_to_card()
	# 设置移动到的位置
	for idx in cards.size():
		var card : CardItem = _init_card_prop(cards[idx])
		var from = card.get_card_position()
		var to = card.get_card_position() + velocity
		if _from_step: from += _from_step * idx
		if _to_step: to += _to_step * idx
		_timer_task.add_task(
			idx * _interval, 
			card, "move_to", [from, to]
		)
	_reset()
	return self


##  移动到位置
## @from  开始的位置（不传入 to 的参数，则这个值为到达的位置）
## @to  到达的位置
## @return  
func move_to(
	_from : Vector2, 
	_to: Vector2 = Vector2.INF
) -> CardItemList:
	_inspect()
	var list : Array = _from_to_card()
	for idx in list.size():
		var card = _init_card_prop(list[idx])
		var from = _from
		var to = _to
		if _to == Vector2.INF:
			from = card.get_card_position()
			to = _from
		if _from_step: from += _from_step * idx
		if _to_step: to += _to_step * idx
		_timer_task.add_task(
			idx * _interval, 
			card, "move_to", [from, to]
		)
	_reset()
	return self


##  根据路径播放动画
## @global  按照全局位置移动
## @return  
func path_follow(path: Path2D, global:bool = false) -> CardItemList:
	var list = []
	for i in get_cards().size():
		list.append(path)
	return paths_follow(list, global)


func paths_follow(paths: Array, global:bool = false) -> CardItemList:
	_inspect()
	var cards : Array = get_cards()
	for idx in cards.size():
		var card : CardItem = _init_card_prop(cards[idx])
		var path_util : PathUtil = get_card_path_util(card, paths[idx])
		path_util._global_pos = global
		var duration = idx * _interval
		_timer_task.add_task(
			duration, path_util, "mark_position"
		)
		_timer_task.add_task(
			duration, card, "interpolate_method", [path_util, "move"]
		)
	_reset()
	return self




#============================================================
#   卡片对应的 PathUtil
#============================================================
var card_path_utl_map = {}

func get_card_path_util(card: CardItem, path: Path2D) -> PathUtil:
	if not card_path_utl_map.has(card):
		card_path_utl_map[card] = PathUtil.new(card, path)
	return card_path_utl_map[card] as PathUtil


class PathUtil:
	var _card: CardItem
	var _curve: Curve2D
	var _origin: Vector2
	var _length: float
	var _global_pos: bool = true
	var _path : Path2D
	
	func _init(card: CardItem, path: Path2D):
		_card = card
		_path = path
		_curve = path.curve
		_length = _curve.get_baked_length()
	
	func mark_position():
		_origin = _card.get_card_position()
	
	# 根据比率设置位置，获取 Path2D 上的设置的路径位置
	func move(ratio: float):
		var p =( _origin 
			+ _curve.interpolate_baked(ratio * _length)
			+ _path.global_position
		)
		_card.set_card_position(p, _global_pos)


